package com.zbkj.service.service.device.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zbkj.common.exception.AppException;
import com.zbkj.common.model.device.Device;
import com.zbkj.common.model.device.MqttConfig;
import com.zbkj.service.dao.device.DeviceDao;
import com.zbkj.service.service.device.DeviceService;
import com.zbkj.service.service.device.MqttConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.UUID;

/**
 * 设备服务实现类
 * +----------------------------------------------------------------------
 * | Author: xiaolic
 * +----------------------------------------------------------------------
 */
@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceDao, Device> implements DeviceService {

    @Autowired
    private MqttConfigService mqttConfigService;

    /**
     * 根据设备ID查找设备
     *
     * @param deviceId 设备ID
     * @return 设备信息
     */
    @Override
    public Device getDeviceById(Long deviceId) {
        if (deviceId == null || deviceId <= 0) {
            return null;
        }
        
        return getById(deviceId);
    }

    /**
     * 根据设备MAC地址查找设备
     *
     * @param macAddress MAC地址
     * @return 设备信息
     */
    @Override
    public Device getDeviceByMac(String macAddress) {
        if (macAddress == null || macAddress.isEmpty()) {
            return null;
        }
        
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getDeviceMac, macAddress);
        queryWrapper.eq(Device::getIsDeleted, false);
        return getOne(queryWrapper);
    }

    /**
     * 根据设备IMEI查找设备
     *
     * @param imei IMEI
     * @return 设备信息
     */
    @Override
    public Device getDeviceByImei(String imei) {
        if (imei == null || imei.isEmpty()) {
            return null;
        }
        
        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getImei, imei);
        queryWrapper.eq(Device::getIsDeleted, false);
        return getOne(queryWrapper);
    }

    @Override
    public Device getDeviceBySn(String deviceSN) {
        if (StrUtil.isBlank(deviceSN)) {
            return null;
        }

        LambdaQueryWrapper<Device> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Device::getSn, deviceSN);
        queryWrapper.eq(Device::getIsDeleted, false);
        return getOne(queryWrapper);
    }
    
    /**
     * 通过字段注册设备并返回设备ID
     *
     * @param macAddress MAC地址
     * @param imei IMEI号
     * @return 设备SN编号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String registerDeviceByFields(String macAddress, String imei) {
        log.info("开始通过字段注册设备，MAC地址: {}, IMEI: {}", macAddress, imei);
        
        if (macAddress == null || macAddress.isEmpty()) {
            log.error("MAC地址不能为空");
            throw new AppException("MAC地址不能为空");
        }
        
        // 检查设备是否已存在
        Device existingDevice = getDeviceByMac(macAddress);
        if (existingDevice != null) {
            log.info("设备已存在，MAC地址: {}, 设备ID: {}", macAddress, existingDevice.getId());
            return existingDevice.getSn();
        }
        
        // 如果有IMEI，也检查IMEI是否已存在
        if (imei != null && !imei.isEmpty()) {
            Device deviceByImei = getDeviceByImei(imei);
            if (deviceByImei != null) {
                log.info("设备已存在，IMEI: {}, 设备ID: {}", imei, deviceByImei.getId());
                return deviceByImei.getSn();
            }
        }
        
        // 创建新设备
        Device device = new Device();
        device.setDeviceMac(macAddress);
        device.setImei(imei);
        device.setSn(generateDeviceSn());
        device.setIsOnline(false);
        device.setLastOnlineTime(null);
        device.setCreatedAt(new Date());
        device.setUpdatedAt(new Date());
        device.setIsDeleted(false);
        
        // 保存设备
        boolean saved = save(device);
        if (!saved) {
            log.error("保存设备失败");
            throw new AppException("保存设备失败");
        }
        
        log.info("设备注册成功，设备SN编号: {}", device.getSn());
        return device.getSn();
    }
    
    /**
     * 根据设备MAC地址获取MQTT配置
     *
     * @param macAddress MAC地址
     * @return MQTT配置信息
     */
    @Override
    public MqttConfig getMqttConfigByMac(String macAddress) {
        if (macAddress == null || macAddress.isEmpty()) {
            log.warn("获取MQTT配置时MAC地址不能为空");
            return mqttConfigService.getDefaultConfig();
        }
        
        Device device = getDeviceByMac(macAddress);
        if (device == null) {
            log.warn("无法找到设备，MAC地址: {}", macAddress);
            return mqttConfigService.getDefaultConfig();
        }
        
        return mqttConfigService.getConfigByDeviceId(device.getId());
    }
    
    /**
     * 根据设备IMEI获取MQTT配置
     *
     * @param imei IMEI
     * @return MQTT配置信息
     */
    @Override
    public MqttConfig getMqttConfigByImei(String imei) {
        if (imei == null || imei.isEmpty()) {
            log.warn("获取MQTT配置时IMEI不能为空");
            return mqttConfigService.getDefaultConfig();
        }
        
        Device device = getDeviceByImei(imei);
        if (device == null) {
            log.warn("无法找到设备，IMEI: {}", imei);
            return mqttConfigService.getDefaultConfig();
        }
        
        return mqttConfigService.getConfigByDeviceId(device.getId());
    }

    /**
     * 生成设备SN编号
     * 直接使用UUID确保唯一性
     *
     * @return 唯一的SN编号
     */
    @Override
    public String generateDeviceSn() {
        // 使用UUID的一部分来确保唯一性
        String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8).toUpperCase();
        
        // 生成年月日格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String dateStr = sdf.format(new Date());
        
        // 组合格式: bm47 + 年月日 + UUID(8位)
        String sn = "bm47-" + dateStr + uuid;
        
        log.info("生成唯一设备SN: {}", sn);
        return sn;
    }

    /**
     * 将字节数组转换为MAC地址格式
     */
    private String bytesToMacAddress(byte[] data, int offset) {
        if (data == null || data.length < offset + 6) {
            return null;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(String.format("%02X", data[offset + i]));
            if (i < 5) {
                sb.append(":");
            }
        }
        
        return sb.toString();
    }

    /**
     * 将字节数组转换为十六进制字符串
     */
    private String bytesToHexString(byte[] data, int offset, int length) {
        if (data == null || data.length < offset + length) {
            return null;
        }
        
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(String.format("%02X", data[offset + i]));
        }
        
        return sb.toString();
    }

    /**
     * 将字节数组转换为长整型
     */
    private long bytesToLong(byte[] data, int offset, int length) {
        if (data == null || data.length < offset + length) {
            return 0;
        }
        
        long value = 0;
        for (int i = 0; i < length; i++) {
            value |= ((long)(data[offset + i] & 0xFF)) << (8 * i);
        }
        
        return value;
    }
}
